package org.rabbitmq.mq02.mqServer.core;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.rabbitmq.mq02.common.ConsumerEnv;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 创建队列类
 */
@Data
public class MSGQueue {
    //队列唯一标识
    private String name;
    //是否持久化 ,默认持久化
    private boolean durable = true;
    //是否自动删除 ,默认不自动删除
    private boolean autoDelete = false;
    //选填参数
    private Map<String,Object> args = new HashMap<>();
    //给队列添加一个订阅者集合

    //此处再添加一个属性:订阅该队列的消费者集合
    private List<ConsumerEnv> consumerEnvList = new ArrayList<>();
    //当订阅队列的消费者不止一个时 , 规定以轮训的方式消费消息
    //再添加一个属性,记录当前轮到哪个消费者消费消息了
    //这里使用AtomicInteger类来实现,目的是不让手动修改,且要实现自增的功能
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    //添加一个新的订阅者(消费者)
    public void addConsumerEnv(ConsumerEnv consumerEnv){
        consumerEnvList.add(consumerEnv);
    }

    //挑选一个订阅者,消费当前消息,按照轮训的方式
    public ConsumerEnv chooseConsumerEnv(){
        if(consumerEnvList.isEmpty()){
            //当前该队列还没有消费者订阅
            System.out.println("[MSGQueue] 当前该队列没有订阅者");
            return null;
        }
        //按照轮训的方式获取一个要消费消息的订阅者下标
        int index = atomicInteger.get()%consumerEnvList.size();
        //让轮训值 自增
        atomicInteger.getAndIncrement();
        return consumerEnvList.get(index);
    }


    //这里的args的数据类型是Map,数据库中没有对应的数据类型,
    // 存入数据库时,要转换成String类型,
    //从数据库中读取时,要转换成Map类型
    public String getArgs(){
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writeValueAsString(args);
        } catch (JsonProcessingException e) {
//            throw new RuntimeException(e);
            e.printStackTrace();
        }
        return "{}";
    }

    public void setArgs(String args) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        this.args = mapper.readValue(args, new TypeReference<HashMap<String,Object>>() {});
    }

    public void setArgs(Map<String,Object> args){
        this.args = args;
    }
}
